package com.yonyou.pmclouds.workstartreport.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.yonyou.pmclouds.ApplicationConsts;
import com.yonyou.pmclouds.basecom.billstatus.BillStatusConst;
import com.yonyou.pmclouds.basecom.bp.processor.*;
import com.yonyou.pmclouds.basecom.bp.template.SingleDeleteBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleInsertBpTemplate;
import com.yonyou.pmclouds.basecom.bp.template.SingleUpdateBpTemplate;
import com.yonyou.pmclouds.basecom.consts.BillTypeConst;
import com.yonyou.pmclouds.basecom.consts.CheckItemConst;
import com.yonyou.pmclouds.basecom.entity.SuperVO;
import com.yonyou.pmclouds.basecom.exception.BusinessException;
import com.yonyou.pmclouds.picture.entity.PictureParamVO;
import com.yonyou.pmclouds.picture.rmiitf.PictureRemoteService;
import com.yonyou.pmclouds.plan.plandriven.rmiitf.IScheduleDriven;
import com.yonyou.pmclouds.plan.processor.ScheduleDrivenProcessor;
import com.yonyou.pmclouds.project.processor.ProjectBillUpdateForUpdate;
import com.yonyou.pmclouds.project.processor.UpdateBillCountForDeleteProcessor;
import com.yonyou.pmclouds.project.processor.UpdateBillCountForInsertProcessor;
import com.yonyou.pmclouds.workflow.aspect.PMApprove;
import com.yonyou.pmclouds.workflow.service.rmiitf.IFlowApproveBuziService;
import com.yonyou.pmclouds.workstartreport.entity.WorkStartCheckVO;
import com.yonyou.pmclouds.workstartreport.entity.WorkStartVO;
import com.yonyou.pmclouds.workstartreport.mapper.WorkStartCheckMapper;
import com.yonyou.pmclouds.workstartreport.mapper.WorkStartMapper;
import com.yonyou.pmclouds.workstartreport.process.*;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;

@Service(version = ApplicationConsts.APPLICATION_VERSION, interfaceClass = com.yonyou.pmclouds.workstartreport.rmiitf.WorkStartMaintain.class )
public class
WorkStartMaintainImpl implements com.yonyou.pmclouds.workstartreport.rmiitf.WorkStartMaintain , IFlowApproveBuziService {
    @Autowired
    private WorkStartMapper mapper;
    @Autowired
    private WorkStartCheckMapper checkMapper;
    @Autowired
    private PictureRemoteService pictureService;
    @Autowired
    private ProjectStatusCheckProcessor<WorkStartVO> projectStatusCheckProcessor;
    @Autowired
    private UpdateBillCountForInsertProcessor.UpdateBillCountForInsertProcessorFactory<WorkStartVO> billCountFactory;
    @Autowired
    private UpdateBillCountForDeleteProcessor.UpdateBillCountForDeleteProcessorFactory<WorkStartVO> billCountDeleteFactory;
    @Autowired
    private ProjectBillUpdateForUpdate.ProjectBillForUpdateProcessorFactory<WorkStartVO> billForUpdateProcessorFactory;
    @Autowired
    private BillDrivenProcessorFactory drivenProcessorFactory;
    @Autowired
    private WorkStartProjectLogPostProcess workStartProjectLogPostProcess;
    @Autowired
    private IScheduleDriven scheduleDriven;
    @Autowired
    private DocCenterProcessor docCenterProcessor;

    //审批时要更改的字段
    private static String[] UPDATE_STATUS = {WorkStartVO.BILLSTATUS};
    //主表需要更新的字段名
    private static String[] UPDATE_FIELDS = {WorkStartVO.BILLSTATUS,WorkStartVO.PKENTERPRISE,WorkStartVO.PKSUPERVISION,WorkStartVO.STARTDATE,WorkStartVO.PKWORKQUALITY};
    //检查项表需要更新的字段
    private static String[] UPDATE_CHECK = {WorkStartCheckVO.LOGO,WorkStartCheckVO.INSTRUCTION,WorkStartCheckVO.QUALIFICATION};

    @PMApprove
    @Override
    public WorkStartVO insert(WorkStartVO workStartVO) throws BusinessException {
        //创建一个单个实体的插入模板对象 传入一个mapper对象
        SingleInsertBpTemplate<WorkStartVO> bp = new SingleInsertBpTemplate<>(mapper);
        //补全字段创建者以及创建时间
        bp.addBeforeProcessor(new AuditInfoInsertProcessor<WorkStartVO>());
        //判断一些不能为空的字段，即传入进来的数据是否符合规范
        bp.addBeforeProcessor(new WorkStartInsertCheckProcessor());
        //添加主表之前，先添加关联子表的字段值
        bp.addBeforeProcessor(new WorkStartInsertProcessor(checkMapper,mapper));
        //检验项目状态,如果项目状态为1，则代表项目已经结束，就会抛项目已结束，无法添加异常。
        bp.addBeforeProcessor(projectStatusCheckProcessor);
        //更新单据数量统计
        bp.addAfterProcessor(billCountFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        //智能日志
        bp.addAfterProcessor(workStartProjectLogPostProcess);
        //添加单据，统一调用process方法
        bp.insert(workStartVO);
        //获取检查项数组
        WorkStartCheckVO[] workStartCheckVOS = workStartVO.getWorkStartCheckVOS();
        //保存图片
        PictureParamVO pictureParamVO = new PictureParamVO(workStartVO.getPkWorkstartreport(), workStartVO.getPkProject(), workStartVO.getBillType());
        for (WorkStartCheckVO w:workStartCheckVOS){
            //以检查项的主键为基准，存入图片，则需要告诉其单据主键，项目主键，以及单据类型
            pictureService.insertPictureForPub(w, pictureParamVO);
        }
        return workStartVO;
    }

    @PMApprove(trigger = "commit")
    @Override
    public WorkStartVO update(WorkStartVO workStartVO) throws BusinessException {
        //创建一个单个实体更新模板对象，传入你要更新的实体的mapper对象以及你想要更新或者说可以更新的字段名。这样在更新时会自动只更新这些字段。
        SingleUpdateBpTemplate<WorkStartVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_FIELDS);
        //添加修改者以及修改时间  这个new就这两个作用
        bp.addBeforeProcessor(new AuditInfoUpdateProcessor<WorkStartVO>());
        //获得更新的检查项数组
        WorkStartCheckVO[] workStartCheckVOS = workStartVO.getWorkStartCheckVOS();
        //遍历数组
        //首先，判断可更新的字段是否更新，若更新，则覆盖原有值，直接更新。若没有更新，则应该先查出来，让其有默认值，这样在更新时，即使不覆盖它，它还是原来的值。
        for (WorkStartCheckVO wsc:workStartCheckVOS){
            //根据单据主键以及原检查项主键查询现存信息的检查项数据。
            WorkStartCheckVO workStartCheckVO = checkMapper.selectPkCheck(workStartVO.getPkWorkstartreport(), wsc.getPkWorkqualitydetail());
            if (ArrayUtils.isNotEmpty(wsc.getPictures())) {
                wsc.setLogo(CheckItemConst.LOGO_ALL_PROSSESS);
            } else if (StringUtils.isNotEmpty(wsc.getInstruction())) {
                wsc.setLogo(CheckItemConst.LOGO_NO_PICTURE);
            } else {
                wsc.setLogo(CheckItemConst.LOGO_NO_DATA);
            }
            //若接收留言为null，代表没有改变，则赋予其原来值。
            if (wsc.getInstruction()==null){
                wsc.setInstruction(workStartCheckVO.getInstruction());
            }
            //为检查项添加主键，为了在调用update时只需要更新这个检查项的字段信息即可
            wsc.setPkCheck(workStartCheckVO.getPkCheck());
        }
        //更新检查项，需要创建一个单个更新实体模板对象，因为需要补全一些例如修改者等字段信息。并且需要告诉检查项哪些字段是可以更新的。
        SingleUpdateBpTemplate<WorkStartCheckVO> bp1 = new SingleUpdateBpTemplate<>(checkMapper, UPDATE_CHECK);
        //检查项添加修改者以及修改时间
        bp1.addBeforeProcessor(new AuditInfoUpdateProcessor<WorkStartCheckVO>());
        //更新检查项
        bp.addBeforeProcessor(new WorkStartSingleUpdateProcessor(checkMapper,pictureService,bp1));
        //检验项目状态，判断项目是否已经竣工
        bp.addBeforeProcessor(projectStatusCheckProcessor);
        //更新统计单据，主要更新项目单据统计单据状态
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        //更新主表数据
        bp.update(workStartVO);
        return workStartVO;
    }

    @Override
    public void delete(WorkStartVO workStartVO) throws BusinessException {
        SingleDeleteBpTemplate<WorkStartVO> bp = new SingleDeleteBpTemplate<>(mapper);
        bp.addBeforeProcessor(new WorkStartDeleteProcessor(mapper,checkMapper));
        //更新单据
        bp.addAfterProcessor(billCountDeleteFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        bp.delete(workStartVO);
    }

    @Override
    public SuperVO approveByPkBill(String pk_bill, byte billStatus) throws BusinessException {
        if(StringUtils.isEmpty(pk_bill)){
            return null;
        }
        //根据单据主键获得开工报告实体
        WorkStartVO workStartVO = mapper.selectReport(pk_bill);
        //告诉更改模板要更改的字段
        SingleUpdateBpTemplate<WorkStartVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_STATUS);
        //将实体的状态改变
        workStartVO.setBillstatus(billStatus);
        // 单据驱动项目状态变化
        bp.addAfterProcessor(drivenProcessorFactory.getBillDrivenProcessor(BillTypeConst.WORKSTART_BILLTYPE,
                new BillDrivenProcessorFactory.AdditionalInfoToDriven<WorkStartVO>() {
                    @Override
                    public Map<String, Object> extractAdditionalInfo(WorkStartVO vo, WorkStartVO orig) throws BusinessException {
                        Map<String, Object> extMap = new HashMap<String, Object>();
                        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
                        if(vo.getStartdate() != null){
                            extMap.put("start_work_date",sdf.format(vo.getStartdate()));
                        }
                        return extMap;
                    }
                }));
        //更新项目单据表中单据的状态
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        // 驱动计划
        bp.addAfterProcessor(new ScheduleDrivenProcessor<WorkStartVO>(scheduleDriven));
        bp.addAfterProcessor(docCenterProcessor);
        bp.update(workStartVO);
        return workStartVO;
    }

    @Override
    public SuperVO rejectByPkBill(String pk_bill) throws BusinessException {
        if(StringUtils.isEmpty(pk_bill)){
            return null;
        }
        //根据单据主键获得开工报告实体
        WorkStartVO workStartVO = mapper.selectReport(pk_bill);
        //告诉更改模板要更改的字段
        SingleUpdateBpTemplate<WorkStartVO> bp = new SingleUpdateBpTemplate<>(mapper, UPDATE_STATUS);
        //将实体的状态改变
        workStartVO.setBillstatus(BillStatusConst.COMMON_REJECT_STATUS);
        bp.addAfterProcessor(billForUpdateProcessorFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        bp.update(workStartVO);
        return workStartVO;
    }

    @Override
    public SuperVO queryDetailForWorkFlow(String pk_bill) throws BusinessException {
        return mapper.selectReport(pk_bill);
    }

    @Override
    public String getBillType() {
        return BillTypeConst.WORKSTART_BILLTYPE;
    }

    @Override
    public SuperVO deleteBill(SuperVO businessVO) throws BusinessException {
        SingleDeleteBpTemplate<WorkStartVO> bp = new SingleDeleteBpTemplate<>(mapper);
        bp.addAfterProcessor(billCountDeleteFactory.getProcessor(BillTypeConst.WORKSTART_BILLTYPE));
        return bp.delete((WorkStartVO) businessVO);
    }

    @Override
    public Object getMapper() {
        return mapper;
    }
}
